package api

import (
	"animal/octopus/common"
	"animal/octopus/core"
	"encoding/csv"
	"fmt"
	"net/http"

	"github.com/gin-gonic/gin"
	log "github.com/sirupsen/logrus"
)

// ------------------------------------------------------------------------------
//
// ------------------------------------------------------------------------------
func GetReportRuleList(c *gin.Context) {
	log.WithFields(log.Fields{"request": c.Request}).Info(c.Request.URL.Path)

	moduleID, err := common.MustGetRequestIntParam(c, "module")
	if err != nil {
		c.PureJSON(http.StatusBadRequest, gin.H{
			"code":    common.ErrInvalidParam,
			"message": err.Error(),
			"result":  nil,
		})
		log.Error(err)
		return
	}

	if topoRules, err := core.GetReportRuleList(uint(moduleID)); err != nil {
		c.PureJSON(http.StatusInternalServerError, gin.H{
			"code":    0,
			"type":    "success",
			"message": "success",
			"result":  nil,
		})
	} else {
		c.PureJSON(http.StatusOK, gin.H{
			"code":    0,
			"type":    "success",
			"message": "success",
			"result":  topoRules,
		})
	}
}

// ------------------------------------------------------------------------------
//
// ------------------------------------------------------------------------------
func CreateReportRule(c *gin.Context) {
	log.WithFields(log.Fields{"request": c.Request}).Info(c.Request.URL.Path)

	var param common.CreateReportRuleParam
	if err := c.ShouldBindJSON(&param); err != nil {
		c.PureJSON(http.StatusBadRequest, gin.H{
			"code":    0,
			"message": "error",
			"result":  nil,
		})
		log.WithField("error", err).Error("invalid request")
		return
	}

	if ruleID, err := core.CreateReportRule(param); err != nil {
		c.PureJSON(http.StatusInternalServerError, gin.H{
			"code":    err.(*common.ErrCode).Code,
			"message": err.(*common.ErrCode).Message,
			"result":  nil,
		})
	} else {
		c.PureJSON(http.StatusOK, gin.H{
			"code":    0,
			"message": "success",
			"result": common.CreateReportRuleRspData{
				RuleID: ruleID,
			},
		})
	}
}

// ------------------------------------------------------------------------------
//
// ------------------------------------------------------------------------------
func EditReportRule(c *gin.Context) {
	log.WithFields(log.Fields{"request": c.Request}).Info(c.Request.URL.Path)

	var param common.EditReportRuleParam
	if err := c.ShouldBindJSON(&param); err != nil {
		c.PureJSON(http.StatusBadRequest, gin.H{
			"code":    0,
			"message": "error",
			"result":  nil,
		})
		log.WithField("error", err).Error("invalid request")
		return
	}

	if err := core.EditReportRule(param); err != nil {
		c.PureJSON(http.StatusInternalServerError, gin.H{
			"code":    err.(*common.ErrCode).Code,
			"message": err.(*common.ErrCode).Message,
			"result":  nil,
		})
	} else {
		c.PureJSON(http.StatusOK, gin.H{
			"code":    0,
			"message": "success",
			"result":  nil,
		})
	}
}

// ------------------------------------------------------------------------------
//
// ------------------------------------------------------------------------------
func DeleteReportRule(c *gin.Context) {
	log.WithFields(log.Fields{"request": c.Request}).Info(c.Request.URL.Path)

	var param common.DeleteReportRuleParam
	if err := c.ShouldBindJSON(&param); err != nil {
		c.PureJSON(http.StatusBadRequest, gin.H{
			"code":    0,
			"message": "error",
			"result":  nil,
		})
		log.WithField("error", err).Error("invalid request")
		return
	}

	if err := core.DeleteReportRule(param); err != nil {
		c.PureJSON(http.StatusInternalServerError, gin.H{
			"code":    err.(*common.ErrCode).Code,
			"message": err.(*common.ErrCode).Message,
			"result":  nil,
		})
	} else {
		c.PureJSON(http.StatusOK, gin.H{
			"code":    0,
			"message": "success",
			"result":  nil,
		})
	}
}

// ------------------------------------------------------------------------------
//
// ------------------------------------------------------------------------------
func ImportReportRule(c *gin.Context) {
	log.WithFields(log.Fields{"request": c.Request}).Info(c.Request.URL.Path)

	moduleID, err := common.MustGetRequestIntParam(c, "module")
	if err != nil {
		c.PureJSON(http.StatusBadRequest, gin.H{
			"code":    common.ErrInvalidParam,
			"message": err.Error(),
			"result":  nil,
		})
		log.Error(err)
		return
	}

	fileHeader, err := c.FormFile("file")
	if err != nil {
		c.PureJSON(http.StatusBadRequest, gin.H{
			"code":    common.ErrGeneralError,
			"message": "get file failed",
			"result":  nil,
		})
		return
	}

	file, err := fileHeader.Open()
	if err != nil {
		c.PureJSON(http.StatusInternalServerError, gin.H{
			"code":    common.ErrGeneralError,
			"message": "open file failed",
			"result":  nil,
		})
		log.WithField("error", err).Error("open file failed")
		return
	}
	defer file.Close()

	records, err := csv.NewReader(file).ReadAll()
	if err != nil {
		c.PureJSON(http.StatusInternalServerError, gin.H{
			"code":    common.ErrGeneralError,
			"message": "read from file failed",
			"result":  nil,
		})
		log.WithField("error", err).Error("read from file failed")
		return
	}

	var params []common.ImportReportRuleParam
	for _, record := range records { // desc, match type, match rule, parent
		if len(record) != 4 {
			c.PureJSON(http.StatusBadRequest, gin.H{
				"code":    common.ErrInvalidParam,
				"message": fmt.Sprintf("invalid param num:%d", len(record)),
				"result":  nil,
			})
			return
		}

		var param common.ImportReportRuleParam
		param.Desc = record[0]
		param.MatchType = record[1]
		param.MatchRule = record[2]
		param.Parent = record[3]
		params = append(params, param)

		log.WithField("param", common.MustMarshal(param)).
			Info("add import report rule param")
	}

	if err := core.ImportReportRules(uint(moduleID), params); err != nil {
		c.PureJSON(http.StatusBadRequest, gin.H{
			"code":    common.ErrInvalidParam,
			"message": err.Error(),
			"result":  nil,
		})
	} else {
		c.PureJSON(http.StatusOK, gin.H{
			"code":    0,
			"message": "success",
			"result":  nil,
		})
	}
}
